/*
 * 文件名称:          ICache.java
 * 时间:             2014-8-19 上午10:12:30
 */

package com.hyfrogx.modules.app.utils;

import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 *  简单的缓存处理，根据系统的部署情况，采用不同的实现。
 *  在该缓存中，一个缓存实例中的所有数据的有效时间是一致的，
 *  即是如果这是该缓存实例的有效时间是1000ms，则进入该缓存
 *  中的所有对象的有效时间都是1000ms，在1000ms后，该进入该
 *  缓存的该对象就失效了；如果对于进入缓存的对象需要不同的失效时间
 *  则根据需要进入到不同的缓存实例中。
 *  对于只有一台web服务器的情况，一般只采用内存实现，
 *  如果需要缓存大量的数据内容，可以采用独立缓存服务的实现。
 */
public interface ICache<K, V>
{

    /**
     * 缓存名，在系统中所有的缓存不可重名
     * @return 获取缓存实例对象的命名
     */
    String getName();
    
    /**
     * 设置缓存命名
     *
     * @param name 缓存实例对象名
     */
    void setName(String name);

    /**
     * 缓存的最大对象数，小于等于0表示无限制
     *
     * @return 缓存的最大对象数
     */
    int getMaxCacheSize();

    /**
     * 设置缓存的最大对象数，小于等于0表示无限制
     *
     * @param maxSize 缓存的最大对象数
     */
    void setMaxCacheSize(int maxSize);

    /**
     * 对象在缓存中的生存时间，小于等于0表示无限制，及该对象
     * 会一直存在该缓存中，除非显示调用去除
     *
     * @return the maximum 对象生存最大毫秒时间。
     */
    long getMaxLifetime();

    /**
     * 对象在缓存中的生存时间，小于等于0表示无限制，及该对象
     * 会一直存在该缓存中，除非显示调用去除
     *
     * @param maxLifetime 对象生存最大毫秒时间。
     */
    void setMaxLifetime(long maxLifetime);
    
    /**
     * 打开批量操作处理，在打开后对应的操作完成，，则必须调用关闭
     * 批量操作的方法closeBatch，否则修改的数据不能进入缓存，也
     * 不能获取到真正的数据.
     * 
     * 一旦打开该批量操作处理，则在关闭之前，后续后续的设置操作
     * 或等待到关闭后才真正执行，此时所有获取方法返回的值全部为
     * null值，因此对于该缓存来说，该批量操作时非线程安全的，不
     * 可使该缓存对象在开启批量方式后，在多个线程中使用，否则
     * 会出现各种意想不到的错误。
     * 
     */
    void openBatch();
    
    /**
     * 关闭批量操作处理。
     * 
     */
    void closeBatch();
    
    /**
     * 当前缓存中的对象数量
     */
    int size();

    /**
     * 缓存是否为空
     *
     * @return 缓存是否为空
     */
    boolean isEmpty();

    /**
     * 缓存中是否已经有key值
     * @param key 可以值
     * @return 返回是否有该key值的对象
     */
    boolean containsKey(K key);
    
    /**
     * 获取key值对应的对象，该值是作为缓存key的整体值设置获取的。
     * @param key 设置的key值
     * @return 缓存中的对象
     */
    V get(K key);
    
    /**
     * 
     * 获取key值对应的对象，并在原来基础上重置对象的到期时间
     * @param key 设置的key值
     * @param resetTime 为true表示如果对象存在时候，则获取对象后，对象的生存周期从新开始，既是
     * 从获取时刻开始按照整个缓存设置的周期从0开始计算。如果为false，这保持生存周期不会重新开始，
     * 此时同调用无该参数的方法一致。
     * @return 缓存中的对象
     */
    V get(K key, boolean resetTime);
    
    /**
     * 单独设置key的过期时间，不管整体缓存的过期时间
     * @param millisecond
     */
    //void expireKey(K key, long millisecond);
    
    /**
     * 缓存中一次设置多个值，缓存中的key-value值对应给定map中的key-value值
     * @param m 需要设置的缓存key-value值对
     */
    void multiSet(Map<K, V> m);

    /**
     * 设置缓存对象
     * @param key 可以值
     * @param value 具体对象
     */
    void put(K key, V value);

    /**
     * 删除key值对象
     * @param key key值
     */
    void remove(K key);
    
    /**
     * 清空缓存
     */
    void clear();
    
    /**
     * 获取该缓存对象中的所有key值
     * @return 缓存中所有key值
     */
    Set<K> keySet();
    
    /**
     * 将缓存中key对应的数值增加delta值，如果key对应的值不存在，则
     * 先初始化值为0，然后在增加delta值。如果key对应的值不是数值，则
     * 报错误。设置后该key值的有效期重新开始计算
     * @param key 缓存key值
     * @param delta 需要增加的值
     * @return 最后结果值
     */
    Long increment(K key, long delta) throws Exception;    
    
    /**
     * 当不存在key的值的时候，设置key的值为value，如果存在key的值
     * 则不能设置。如果设置成功，则值的有效期为整个缓存的有效期
     * @param key
     * @param value
     * @return 设置成功返回true，设置失败返回false。
     */
    boolean setIfAbsent(K key, V value);

    /**
     * 删除key指定的map值中以hashKeys为key的值，即是
     * 在缓存中key值对应的值为map对象，该方法删除该map对象中的hashKeys指定的值
     * @param key 需要获取的缓存的key
     * @param hashKeys map值中的key
     */
    void delete(K key, Object... hashKeys);

    /**
     * 判断缓存中key指定的map值中是否有hashkey值指定的对象，
     * 即是缓存中key值对应的值为map对象，该方法返回该map对象中是否有hashkey对应的值
     * @param key 需要获取的缓存的key
     * @param hashKey map值中的key
     * @return
     */
    boolean hasKey(K key, Object hashKey);
    
    /**
     * 获取缓存中key指定的map中haskkey值指定的对象
     * 即是缓存中key值对应的值为map对象，该方法返回该map对象中hashkey对应的值
     * @param key 需要获取的缓存的key
     * @param hashKey map值中的key
     * @return
     */
    V get(K key, Object hashKey);
    
    /**
     * 获取缓存中key指定的map中haskkey值指定的对象
     * 即是缓存中key值对应的值为map对象，该方法返回该map对象中hashkey对应的值
     * @param key 需要获取的缓存的key
     * @param hashKey map值中的key
     * @param resetTime 为true表示如果对象存在时候，则获取对象后，对象的生存周期从新开始，既是
     * 从获取时刻开始按照整个缓存设置的周期从0开始计算。如果为false，这保持生存周期不会重新开始，
     * 此时同调用无该参数的方法一致。
     * @return
     */
    V get(K key, Object hashKey, boolean resetTime);
    
    /**
     * 将缓存中key对应的map值指定的hashkey中的数值增加delta值，如果key对应的值不存在，
     * 则先建立一个map，如果hashkey不存在先初始化值为0，然后在增加delta值。
     * 如果key对应的值不是数值，则
     * 报错误。设置后该key值的有效期重新开始计算
     * @param key 对应的
     * @param hashKey
     * @param delta
     * @return
     */
    Long increment(K key, Object hashKey, long delta) throws Exception;
    
    /**
     * 获取缓存中key对应的map值的key值，如果key对应的值不是map类型，
     * 则返回null
     * @param key
     * @return
     */
    Set<Object> keys(K key);
    
    /**
     * 在缓存中设置map值，该方法设置不同于put方法是，这里map值不是作为key的一个
     * 整体值设置，而是以二次map的方式设置；即是通过该方式设置的map值，可以通过
     * get（key，hashkey）获取map中的一个具体值，而通过put（k， v）设置的值
     * 不可以获取map中的一个具体值，只能以map的整体形式回去该值
     * @param key
     * @param m
     */
    void putAll(K key, Map<Object, V> m)  throws Exception;

    /**
     * 设置缓存中key对应的map值中以hashkey对应的值
     * @param key
     * @param hashKey
     * @param value
     */
    void put(K key, Object hashKey, V value)  throws Exception;

    /**
     * 将缓存中key值对应的map中hashkey设置是为value，如果hashkey已经存在
     * 值，则设置不成功。如果key对应的map不存在，则建立新的map
     * @param key
     * @param hashKey
     * @param value
     * @return
     */
    boolean putIfAbsent(K key, Object hashKey, V value)  throws Exception;

    /**
     * 获取key指定对应的map对象
     * @param key
     * @return
     */
    Map<Object, V> entries(K key);
    
    /**
     * 获取key指定的返回缓存中存在key对应列表的内容的长度，如果key指定的内容不是list值，则返回0；
     * key对应的值如果是list内容，需要按照leftPush,rightPush方式设置进入的值。
     */
    long listSize(K key);

    /**
     * 将一个或多个值 value 插入到列表 key 的表头;如果有多个 value 值，
     * 那么各个 value 值按从左到右的顺序依次插入到表头： 
     * 比如说，对空列表 mylist 执行命令 mylist a b c ，列表的值将是 c b a;
     * 如果已经存在key对应的值不为list，抛出错误
     * @param key
     * @return 返回缓存中存在key对应列表的长度
     */
    long leftPush(K key, V... values) throws Exception;

    /**
     * 将值 value 插入到列表 key 的表头，该操作当且仅当 key 存在并且是一个列表
     * 的时候才有效，否则无效；即是如果在缓存中不存在key指定的列表，则不能value
     * 值不能加入到缓存中，此时返回为0
     * @param key
     * @param value
     * @return 返回缓存中存在key对应列表的长度
     */
    long leftPushIfPresent(K key, V value)  throws Exception;

    /**
     * 将一个或多个值 value 插入到列表 key 的表尾;如果有多个 value 值，
     * 那么各个 value 值按从左到右的顺序依次插入到表尾： 
     * 比如说，对空列表 mylist 执行命令  mylist a b c ，列表的值将是 a b c;
     * 如果已经存在key对应的值不为list，抛出错误
     * @param key
     * @param values
     * @return 返回列表的长度
     */
    long rightPush(K key, V... values)  throws Exception;

    /**
     * 将值 value 插入到列表 key 的表尾，该操作当且仅当 key 存在并且是一个列表
     * 的时候才有效，否则无效；即是如果在缓存中不存在key指定的列表，则不能value
     * 值不能加入到缓存中，此时返回为0
     * @param key
     * @param value
     * @return 返回缓存中存在key对应列表的长度
     */
    long rightPushIfPresent(K key, V value)  throws Exception;

    /**
     * 将 key对应的列表值中下标为 index的元素的值设置为 value；即是替换原index
     * 位置的值；当 index 参数超出范围，或不存在key对应的列表时候，返回一个错误
     * @param key
     * @param index
     * @param value
     */
    void set(K key, long index, V value)  throws Exception;

    /**
     * 根据参数 count 的值，移除key对应列表中与参数 value 相等的元素；
     * count 的值可以是以下几种：
     * count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count
     * count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值
     * count = 0 : 移除表中所有与 value 相等的值
     * @param key
     * @param count
     * @param value
     * @return 返回缓存中存在key对应列表的长度
     */
    long remove(K key, long count, Object value);

    /**
     * 返回key对应的列表中下标为 index 的元素；
     * 
     * @param key
     * @param index  0 表示列表的第一个元素，以 1 表示列表的第二个元素，以此类推。
     * 可以使用负数下标，以 -1 表示列表的最后一个元素， -2 表示列表的倒数第二个元素，以此类推
     * @return
     */
    V index(K key, long index);

    /**
     * 移除并返回 key对应的列表中的列表头元素
     * @param key
     * @return
     */
    V leftPop(K key);

    /**
     * 移除并返回 key对应的列表中的列表尾元素
     * @param key
     * @return
     */
    V rightPop(K key);
    
    /**
     * 单独设置缓存中某个key值对应的缓存数据的实效时间，单位为毫秒。
     * 如果缓存中有该key值数据，则该数据从调用该方法开始，
     * 到给定millis毫秒后实效。
     * 
     * @param key, 给定缓存key值
     * @param millis， 给定实现毫秒时间
     */
    void expire(K key, long millis);
    
    /**
     * 单独设置缓存中某个key值对应的缓存数据的实效时间，单位为unit指定单位。
     * 如果缓存中有该key值数据，则该数据从调用该方法开始，
     * 到给定time时间及unit指定单位后实效。
     * 
     * @param key， 缓存key值
     * @param time， 实现时间值
     * @param unit， 实现时间单位
     */
    void expire(K key, long time, TimeUnit unit);
    
    /**
     * 单独设置缓存中某个key值对应的缓存数据的在指定date时间
     * 时候实效 
     * @param key，缓存key值
     * @param date，缓存实现时间点
     */
    void expireAt(K key, Date date);

}
